package com.suray.basic.wcs.time;

import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.path.core.Route;
import com.suray.basic.wcs.path.core.api.impl.DifFloorRouteFactoryImp;
import com.suray.basic.wcs.time.bo.WCSTimeModuleBO;
import com.suray.basic.wcs.time.bo.WCSTimeModuleResultBO;

import java.util.*;

public class WCSTimeModule {

    /**
     * 点集合的估算时间方式：输入为List<Node> 与车辆信息。计算List<Node> 内某个个节点的经过时间（每个Node时间为车辆行驶时间与动作执行时间），
     * 再计算对于整个List某个节点要等到多久经过，并将这个两个值赋值到Node里，让后构造出Node链表。计算完成后将List<Node>对象返回。
     *
     * @param nodeList
     * @param wcsTimeModuleBO
     * @return
     */
    public static WCSTimeModuleResultBO<List<Node>> calculateNodeListPassTime(List<Node> nodeList, WCSTimeModuleBO wcsTimeModuleBO) {
        List<Node> newList = nodeList;
//        Collections.addAll(newList, new Node[nodeList.size()]);
//        Collections.copy(newList, nodeList);
        WCSTimeModuleResultBO<List<Node>> wcsTimeModuleResultBO = new WCSTimeModuleResultBO<>(newList);
        for (int i = 0; i < newList.size(); i++) {
            Node currentNode = newList.get(i);
            if (i + 1 < newList.size()) {
                Node nextNode = newList.get(i + 1);
                currentNode.nextNode = nextNode;
                nextNode.preNode = currentNode;
            }
        }
        if (newList.size() > 0) {
            newList.get(0).calculatePassTimeNoTask(wcsTimeModuleBO.getSpeed(), 0, wcsTimeModuleBO.getPalletUpTime(), wcsTimeModuleBO.getPalletDownTime(), wcsTimeModuleBO.getDirectionTime());
            wcsTimeModuleResultBO.setTotalTime(newList.get(newList.size() - 1).passTime);
        }
        wcsTimeModuleResultBO.setNodes(newList);
        return wcsTimeModuleResultBO;
    }

    /**
     * 路程集合的估算时间方式：输入为List<Route> 与车辆信息。计算List<Route> 中每个Route内每个Path调用路径集合的估算时间方式，
     * 并将一个Route的终点作为下一个Route的起点链表的父节点。计算完成后构建一个包含时间的List<Route>与所有点集合的对象并返回
     *
     * @param routeList
     * @param wcsTimeModuleBO
     * @return
     */
    public static WCSTimeModuleResultBO<List<Route>> calculateRouteListPassTime(List<Route> routeList, WCSTimeModuleBO wcsTimeModuleBO) {
        WCSTimeModuleResultBO<List<Route>> wcsTimeModuleResultBO = new WCSTimeModuleResultBO<>(routeList);
        List<Node> moduleNodeList = new ArrayList<>();
        for (int ri = 0; ri < routeList.size(); ri++) {
            List<Node> nodeList = routeList.get(ri).getNodeList();
            Node preNode = null;
            if (moduleNodeList.size() > 0) {
                preNode = moduleNodeList.get(moduleNodeList.size() - 1);
                if (nodeList.size() > 0 && nodeList.get(0).equals(preNode)) {
                    nodeList.remove(0);
                }
            }
            for (int i = 0; i < nodeList.size(); i++) {
                Node currentNode = nodeList.get(i);

                if (i == 0 && preNode != null) {
                    currentNode.preNode = preNode;
                    preNode.nextNode = currentNode;
                }
                if (i + 1 < nodeList.size()) {
                    Node nextNode = nodeList.get(i + 1);
                    currentNode.nextNode = nextNode;
                    nextNode.preNode = currentNode;
                }
            }
            if (nodeList.size() > 0) {
                int leadTime = 0;
                if (preNode != null) {
                    leadTime = preNode.passTime;
                }
                nodeList.get(0).calculatePassTimeNoTask(wcsTimeModuleBO.getSpeed(), leadTime, wcsTimeModuleBO.getPalletUpTime(), wcsTimeModuleBO.getPalletDownTime(), wcsTimeModuleBO.getDirectionTime());
                wcsTimeModuleResultBO.setTotalTime(nodeList.get(nodeList.size() - 1).passTime);

            }
            moduleNodeList.addAll(nodeList);
        }
        if (moduleNodeList.size() > 0) {
            wcsTimeModuleResultBO.setTotalTime(moduleNodeList.get(moduleNodeList.size() - 1).passTime);
        }
        wcsTimeModuleResultBO.setNodes(moduleNodeList);
        return wcsTimeModuleResultBO;
    }

    /**
     * 路程集合的估算时间方式：输入为List<Route> 与车辆信息。计算List<Route> 中每个Route内每个Path调用路径集合的估算时间方式，
     * 并将一个Route的终点作为下一个Route的起点链表的父节点。计算完成后构建一个包含时间的List<Route>与所有点集合的对象并返回
     *
     * @param routeList
     * @param wcsTimeModuleBO
     * @return
     */
    public static WCSTimeModuleResultBO<List<Route>> calculateRouteListPassTime(List<Route> routeList, WCSTimeModuleBO wcsTimeModuleBO, Integer key) {
        WCSTimeModuleResultBO<List<Route>> wcsTimeModuleResultBO = new WCSTimeModuleResultBO<>(routeList);
        List<Node> moduleNodeList = new ArrayList<>();
        for (int ri = 0; ri < routeList.size(); ri++) {
            List<Node> nodeList = routeList.get(ri).getNodeList();
            Node preNode = null;
            if (moduleNodeList.size() > 0) {
                preNode = moduleNodeList.get(moduleNodeList.size() - 1);
                if (nodeList.size() > 0 && nodeList.get(0).equals(preNode)) {
                    nodeList.remove(0);
                }
            }
            for (int i = 0; i < nodeList.size(); i++) {
                Node currentNode = nodeList.get(i);

                if (i == 0 && preNode != null) {
                    currentNode.preNode = preNode;
                    preNode.nextNode = currentNode;
                }
                if (i + 1 < nodeList.size()) {
                    Node nextNode = nodeList.get(i + 1);
                    currentNode.nextNode = nextNode;
                    nextNode.preNode = currentNode;
                }
            }
            if (nodeList.size() > 0) {
                int leadTime = 0;
                if (preNode != null) {
                    leadTime = preNode.passTime;
                }
                nodeList.get(0).calculatePassTime(wcsTimeModuleBO.getSpeed(), leadTime, wcsTimeModuleBO.getPalletUpTime(), wcsTimeModuleBO.getPalletDownTime(), wcsTimeModuleBO.getDirectionTime(), key);
                wcsTimeModuleResultBO.setTotalTime(nodeList.get(nodeList.size() - 1).passTime);

            }
            moduleNodeList.addAll(nodeList);
        }
        if (moduleNodeList.size() > 0) {
            wcsTimeModuleResultBO.setTotalTime(moduleNodeList.get(moduleNodeList.size() - 1).passTime);
        }
        wcsTimeModuleResultBO.setNodes(moduleNodeList);
        return wcsTimeModuleResultBO;
    }

    /**
     * 任务的估算时间方式：输入为任务，执行起点与车辆信息。先为任务规划执行起点到任务起点，任务起点到任务终点的路径，
     * 获得到List<Route>。再调用路程集合的估算时间方式计算出整个任务完成所需的时间。计算完成后构建一个包含时间的List<Route>与所有点集合的对象并返回。
     *
     * @param start
     * @param end
     * @param palletStatus
     * @param wcsTimeModuleBO
     * @param map
     * @return
     */
    public static WCSTimeModuleResultBO<List<Route>> calculateTaskPassTime(Node start, Node end, boolean palletStatus, WCSTimeModuleBO wcsTimeModuleBO, List<Node> map) {
        List<Integer> layers = new ArrayList<>();
        layers.add(start.getZ());
        layers.add(end.getZ());
        DifFloorRouteFactoryImp routeFactory = new DifFloorRouteFactoryImp(map, null, wcsTimeModuleBO, 0);
        List<Route> routeList = routeFactory.createRoute(start, end, palletStatus);
        WCSTimeModuleResultBO<List<Route>> wcsTimeModuleResultBO = new WCSTimeModuleResultBO<>(routeList);
        List<Node> moduleNodeList = new ArrayList<>();
        for (int ri = 0; ri < routeList.size(); ri++) {
            List<Node> nodeList = routeList.get(ri).getNodeList();
            Node preNode = null;
            if (moduleNodeList.size() > 0) {
                preNode = moduleNodeList.get(moduleNodeList.size() - 1);
            }
            for (int i = 0; i < nodeList.size(); i++) {
                Node currentNode = nodeList.get(i);
                if (i == 0 && preNode != null) {
                    currentNode.preNode = preNode;
                    preNode.nextNode = currentNode;
                }
                if (i + 1 < nodeList.size()) {
                    Node nextNode = nodeList.get(i + 1);
                    currentNode.nextNode = nextNode;
                    nextNode.preNode = currentNode;
                }
            }
            if (nodeList.size() > 0) {
                int leadTime = 0;
                if (preNode != null) {
                    leadTime = preNode.passTime;
                }
                nodeList.get(0).calculatePassTimeNoTask(wcsTimeModuleBO.getSpeed(), leadTime, wcsTimeModuleBO.getPalletUpTime(), wcsTimeModuleBO.getPalletDownTime(), wcsTimeModuleBO.getDirectionTime());
                wcsTimeModuleResultBO.setTotalTime(nodeList.get(nodeList.size() - 1).passTime);

            }
            moduleNodeList.addAll(nodeList);
        }
        if (moduleNodeList.size() > 0) {
            wcsTimeModuleResultBO.setTotalTime(moduleNodeList.get(moduleNodeList.size() - 1).passTime);
        }
        wcsTimeModuleResultBO.setNodes(moduleNodeList);
        return wcsTimeModuleResultBO;
    }

    /**
     * 根据传入的当前点，重新计算点集合内的经过时间
     *
     * @param nodeList
     * @param wcsTimeModuleBO
     * @param currentNode
     * @return
     */
    public static WCSTimeModuleResultBO<List<Node>> cleanAndReCalculateNodeListPassTime(List<Node> nodeList, WCSTimeModuleBO wcsTimeModuleBO, Node currentNode) {
        WCSTimeModuleResultBO<List<Node>> wcsTimeModuleResultBO = new WCSTimeModuleResultBO<>(nodeList);
        for (int i = 0; i < nodeList.size(); i++) {
            Node node = nodeList.get(i);
            if (currentNode != null && node.equals(currentNode)) {
                currentNode = node;
                break;
            }
        }
        if (currentNode != null) {
            currentNode.calculatePassTimeNoTask(wcsTimeModuleBO.getSpeed(), 0, wcsTimeModuleBO.getPalletUpTime(), wcsTimeModuleBO.getPalletDownTime(), wcsTimeModuleBO.getDirectionTime());
            currentNode.cleanPassTime();
        }
        wcsTimeModuleResultBO.setNodes(nodeList);
        return wcsTimeModuleResultBO;
    }
}
